#include "protection.h"
#include <QDebug>
#include <QStandardPaths>
#include <QSettings>
#include <QFileInfo>

// 静态成员初始化
QByteArray Protection::s_integrityHash;

bool Protection::performAntiDebugCheck()
{
    randomDelay();

    bool result = true;
    int checkCount = 0;
    int passCount = 0;

    // 多重检测，任何一个失败都认为有调试器
    checkCount++;
    if (!isDebuggerPresent()) {
        result = false;
    } else {
        passCount++;
    }

    checkCount++;
    if (!checkRemoteDebugger()) {
        result = false;
    } else {
        passCount++;
    }

    checkCount++;
    if (!checkDebuggerByTiming()) {
        result = false;
    } else {
        passCount++;
    }

    checkCount++;
    if (!checkDebuggerByException()) {
        result = false;
    } else {
        passCount++;
    }


    randomDelay();
    return result;
}

bool Protection::isDebuggerPresent()
{
#ifdef _WIN32
    return !IsDebuggerPresent();
#elif __APPLE__
    int mib[4];
    struct kinfo_proc info;
    size_t size = sizeof(info);

    mib[0] = CTL_KERN;
    mib[1] = KERN_PROC;
    mib[2] = KERN_PROC_PID;
    mib[3] = getpid();

    if (sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, NULL, 0) == 0) {
        return (info.kp_proc.p_flag & P_TRACED) == 0;
    }
    return true;
#elif __linux__
    // Linux: 检查ptrace状态
    if (ptrace(PTRACE_TRACEME, 0, 1, 0) == -1) {
        return false;  // 已经被调试
    }
    ptrace(PTRACE_DETACH, 0, 1, 0);
    return true;
#else
    return true;  // 其他平台默认通过
#endif
}

bool Protection::checkRemoteDebugger()
{
#ifdef _WIN32
    BOOL isRemoteDebuggerPresent = FALSE;
    CheckRemoteDebuggerPresent(GetCurrentProcess(), &isRemoteDebuggerPresent);
    return !isRemoteDebuggerPresent;
#else
    return true;  // 非Windows平台默认通过
#endif
}

bool Protection::checkDebuggerByTiming()
{
    QElapsedTimer timer;
    timer.start();

    // 执行一些简单操作
    volatile int sum = 0;
    for (int i = 0; i < 1000; ++i) {
        sum += i;
    }

    qint64 elapsed = timer.elapsed();

    // 如果执行时间异常长，可能有调试器介入
    return elapsed < 100;  // 100ms 阈值
}

bool Protection::checkDebuggerByException()
{
    try {
        // 尝试一个可能引发异常的操作
        volatile int* p = nullptr;
        if (QRandomGenerator::global()->bounded(2) == 0) {
            return true;  // 随机返回true，增加分析难度
        }
    } catch (...) {
        return false;
    }
    return true;
}

bool Protection::performIntegrityCheck()
{

    QString appPath = QCoreApplication::applicationFilePath();

    QFileInfo fileInfo(appPath);

    QByteArray currentHash = calculateFileHash(appPath);

    // 如果没有设置基准哈希，跳过检查
    if (s_integrityHash.isEmpty()) {
        s_integrityHash = currentHash;
        return true;
    }

    bool result = (currentHash == s_integrityHash);

    return result;
}

void Protection::setIntegrityHash(const QByteArray& hash)
{
    s_integrityHash = hash;
}

QByteArray Protection::calculateFileHash(const QString& filePath)
{
    QFile file(filePath);
    if (!file.open(QIODevice::ReadOnly)) {
        return QByteArray();
    }

    QCryptographicHash hash(QCryptographicHash::Sha256);
    if (hash.addData(&file)) {
        return hash.result();
    }

    return QByteArray();
}

QByteArray Protection::encryptAuthData(const QByteArray& data)
{
    QByteArray key = generateKey();
    return xorEncrypt(data, key);
}

QByteArray Protection::decryptAuthData(const QByteArray& encrypted)
{
    QByteArray key = generateKey();
    return xorEncrypt(encrypted, key);  // XOR加密解密是对称的
}

QString Protection::obfuscateString(const QString& str)
{
    QByteArray data = str.toUtf8();
    QByteArray key = generateKey();
    QByteArray encrypted = xorEncrypt(data, key);
    return QString::fromLatin1(encrypted.toBase64());
}

QString Protection::deobfuscateString(const QString& obfuscated)
{
    QByteArray encrypted = QByteArray::fromBase64(obfuscated.toLatin1());
    QByteArray key = generateKey();
    QByteArray data = xorEncrypt(encrypted, key);
    return QString::fromUtf8(data);
}

QString Protection::machineID()
{
    QString id("?");

#ifdef _WIN32
    // Windows: 从注册表获取MachineGuid
    QSettings settings("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Cryptography", QSettings::NativeFormat);
    id = settings.value("MachineGuid", id).toString();
#elif __APPLE__
    // macOS: 通过ioreg获取IOPlatformUUID
    QProcess proc;
    QStringList args;
    args << "-c" << "ioreg -rd1 -c IOPlatformExpertDevice | awk '/IOPlatformUUID/ { print $3; }' | tr -d '\"'";
    proc.start("/bin/sh", args);
    bool finished = proc.waitForFinished(3000);

    if (finished && proc.exitCode() == 0) {
        QString output = proc.readAllStandardOutput().trimmed();
        if (!output.isEmpty()) {
            id = output;
        }
    } else {
    }
#elif __linux__
    // Linux: 从machine-id文件读取
    QStringList fs;
    fs << "/var/lib/dbus/machine-id" << "/etc/machine-id";
    for (const QString &f : fs) {
        QFile file(f);
        if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
            QTextStream in(&file);
            id = in.readAll().trimmed();
            break;
        } else {
        }
    }
#endif

    return id;
}

QString Protection::machineIDHashKey()
{

    QString id = machineID();

    QByteArray rawHash = QCryptographicHash::hash(id.toLatin1(), QCryptographicHash::Md5);
    QString hexhash = rawHash.toHex();

    QStringList groups;
    for (int group = 0; group < 5; group++) {
        QString groupStr = hexhash.mid(group * 4, 4);
        groups << groupStr;
    }

    QString result = groups.join('-').toUpper();

    return result;
}

QByteArray Protection::generateKey()
{
    // 基于机器ID生成密钥
    QString id = machineID();
    QByteArray keyData = id.toUtf8();

    // 添加一些固定盐值
    keyData.append("LongImageReader2024");

    // 使用SHA256生成固定长度密钥
    return QCryptographicHash::hash(keyData, QCryptographicHash::Sha256);
}

QByteArray Protection::xorEncrypt(const QByteArray& data, const QByteArray& key)
{
    if (key.isEmpty()) {
        return data;
    }

    QByteArray result = data;
    int keyLen = key.length();

    for (int i = 0; i < result.length(); ++i) {
        result[i] = result[i] ^ key[i % keyLen];
    }

    return result;
}

void Protection::randomDelay()
{
    int delay = QRandomGenerator::global()->bounded(10, 50);  // 10-50ms
    QThread::msleep(delay);
}